import { EventStreamContentType, fetchEventSource, type FetchEventSourceInit } from "@microsoft/fetch-event-source";
import type { HttpResponseDataType } from "~/types/global";

class RetriableError extends Error { };
class FatalError extends Error { };

export default () => {
    const { token, clearToken } = useToken();
    const { showToast } = useToast();

    const addAuthHeader = (headers?: any) => {
        if (headers) {
            headers.Authorization = `Bearer ${token.value}`;
        } else {
            headers = { Authorization: `Bearer ${token.value}` };
        }
        return headers;
    };

    const errorHandler = (error: any) => {
        // token失效
        if (error.statusCode === 401) {
            clearToken();
            showToast({ msg: 'Please login first!', type: 'warning' });
            navigateTo('/login');
        }
        return Promise.reject(error);
    };

    const createHttpFetch = <T = any>(...args: Required<Parameters<typeof $fetch<HttpResponseDataType<T>>>>) => {
        // 添加auth信息
        args[1].headers = addAuthHeader(args[1].headers);
        return $fetch<HttpResponseDataType<T>>(...args).then(response => response, errorHandler);
    };

    const createReactiveFetch = <T = any>(...args: Required<Parameters<typeof useFetch<HttpResponseDataType<T>>>>) => {
        // 添加auth信息
        args[1].headers = addAuthHeader(args[1].headers);
        return useFetch<HttpResponseDataType<T>>(...args).then(response => response.data, errorHandler);
    };

    const createEventSourceFetch = (url: string, options: FetchEventSourceInit = {}) => {
        // 取出handler
        const { onopen, onmessage } = options;
        // 初始化options
        Object.assign(options, {
            headers: addAuthHeader({ 'Content-Type': 'application/json' }),
            async onopen(response) {
                if (response.ok && response.headers.get('content-type') === EventStreamContentType) {
                    // 合并open handler
                    return onopen?.(response);
                } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
                    //客户端错误通常不可重试：
                    throw new FatalError();
                } else {
                    throw new RetriableError();
                }
            },
            onmessage(e) {
                //如果服务器发出错误消息，抛出异常
                //以便由下面的onerror回调处理：
                if (e.event === 'FatalError') {
                    throw new FatalError(e.data);
                }
                // 合并message handler
                onmessage?.(e);
            },
            onerror(err) {
                throw err; //重新抛出以终止操作
            },
        } as FetchEventSourceInit);
        return fetchEventSource(url, options);
    };

    return { createHttpFetch, createReactiveFetch, createEventSourceFetch };
};